<!--
 * @Author       : xiangmin
 * @File         : 利用vue-dragable-plus来做拖拽排序图片
 * @Date         : 2023-10-31 10:39:11
 * @LastEditors  : xiangmin
 * @LastEditTime : 2024-09-19 09:54:08
-->
<template>
	<section>
		<VueDraggable
			v-model="previewList"
			:animation="150"
			:onEnd="handleDragEnd"
			target=".ant-upload-list-picture-card"
		>
			<a-upload
				multiple
				v-model:file-list="previewList"
				action="/mel/api/uploadpic?picType=3"
				list-type="picture-card"
				:beforeUpload="beforeUploadFile"
				@preview="handlePreview"
				@change="fileChange"
				v-bind="$attrs"
			>
				<CameraOutlined
					v-if="showUploadIcon"
					class="text-30px font-bold"
				/>
			</a-upload>
		</VueDraggable>

		<!-- <div class="hidden">
			<a-image-preview-group
				:key="updateKey"
				:preview="{
					visible,
					current,
					onVisibleChange: isVisible => (visible = isVisible)
				}"
			>
				<a-image
					v-for="item in previewList"
					:key="item.uid"
					:src="item.url || item.response?.data?.url"
				/>
			</a-image-preview-group>
		</div> -->
	</section>
</template>
<script lang="ts" setup>
import Preview from '@/components/CImage'
import { CameraOutlined } from '@ant-design/icons-vue'
import { watchPausable } from '@vueuse/core'
import type { UploadChangeParam, UploadFile } from 'ant-design-vue'
import { uniqueId } from 'lodash-es'
import { nextTick } from 'vue'
import { VueDraggable } from 'vue-draggable-plus'
import useUpload from './useUpload'

const {
	maxSize = 3,
	maxCount = 3,
	valueType = 'array',
	accept = 'image/png,image/jpeg'
} = defineProps<{
	// 如果时单个图片上传的话，必须设定valueType: string
	valueType?: 'string' | 'array'
	maxSize?: number | string
	maxCount?: number | string
	accept?: string
}>()
const { beforeUploadFile } = useUpload(accept, maxSize)
const previewList = ref<UploadFile[]>([])
const modelValue = defineModel<string[] | string>('list', { required: true })
const showUploadIcon = computed(() => {
	if (valueType === 'string') {
		return previewList.value.length < 1
	} else {
		return previewList.value.length < +maxCount
	}
})

const { pause, resume } = watchPausable(
	modelValue,
	src => {
		if (Array.isArray(src)) {
			previewList.value = src.map(url => ({
				uid: uniqueId('file_'),
				name: 'image.png',
				status: 'done',
				url
			}))
		} else if (typeof src === 'string' && src) {
			previewList.value = [
				{
					uid: uniqueId('file_'),
					name: 'image.png',
					status: 'done',
					url: src
				}
			]
		}
	},
	{ immediate: true, deep: true }
)

// fileList改变后
const fileChange = async ({ file, fileList }: UploadChangeParam) => {
	pause()
	const { status, url, response, name, uid } = file
	if (valueType === 'string') {
		if (status === 'removed') {
			modelValue.value = ''
		}
		if (status === 'error' || (status === 'done' && !response?.data?.url)) {
			modelValue.value = ''
			previewList.value = []
			message.error(`${name}上传失败`)
		}
		if (status === 'done' && url) {
			modelValue.value = url
		}
		if (status === 'done' && response?.data?.url) {
			modelValue.value = response?.data?.url
		}
	} else {
		if (status === 'error' || (status === 'done' && !response?.data?.url)) {
			const index = fileList?.findIndex?.(item => item.uid === uid)
			message.error(`${name}上传失败`)
			fileList.splice(index, 1)
		}
		modelValue.value = fileList.map(item => {
			const { status, response, url } = item
			if (status === 'done' && url) return url
			if (status === 'done' && response?.data?.url) return response?.data?.url
		})
	}
	await nextTick()
	resume()
}

const handlePreview = (file: UploadFile) => {
	const group = previewList.value.map(item => item.url || item.response?.data?.url)
	Preview({
		group,
		src: file.url || file.response?.data?.url
	})
}

const updateKey = ref('update')
const handleDragEnd = async () => {
	pause()
	modelValue.value = previewList.value.map(item => item.url || item.response.data.url)
	// 拖拽排序后要强制更新下预览组件
	updateKey.value = 'update' + Math.random()
	await nextTick()
	resume()
}
</script>
<style scoped lang="less">
:deep(.ant-upload-list-item-done) {
	cursor: move;
}

:deep(.ant-upload-list-item-thumbnail) {
	img {
		object-fit: cover !important;
	}
}
</style>
